home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / util / misc / Fudgit233.lha / Source / src / init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-16  |  15.8 KB  |  675 lines

  1. #include <string.h>
  2. #include <math.h>
  3. #include <ctype.h>
  4. #include <stdio.h>
  5. #ifndef NOSTDLIB_H
  6. #include <stdlib.h>
  7. #endif
  8. #ifndef NOUNISTD_H
  9. #include <unistd.h>
  10. #endif
  11. #ifndef NOMALLOC_H
  12. #include <malloc.h>
  13. #endif
  14.  
  15. #include "fudgit.h"
  16. #include "symbol.h"
  17. #include "code.h"
  18. #include "math.tab.h"
  19. #include "head.h"
  20.  
  21. #ifndef M_PI
  22. #define M_PI        3.14159265358979323846
  23. #endif
  24. #ifndef M_E
  25. #define M_E     2.7182818284590452354
  26. #endif
  27.  
  28. extern double Ft_Log(double x),
  29.   Ft_Log10(double x),
  30.   Ft_Sqrt(double x),
  31.   Ft_Exp(double x),
  32.   Ft_integer(double x),
  33.   Ft_Srand(double x),
  34.   Ft_vread(void),
  35.   Ft_Rand(void),
  36.   Ft_Sec(double x),
  37.   Ft_Sech(double x),
  38.   Ft_Cot(double x),
  39.   Ft_Coth(double x),
  40.   Ft_Csc(double x),
  41.   Ft_Csch(double x),
  42.   Ft_Jn(double i, double d),
  43.   Ft_Yn(double i, double d),
  44.   Ft_Y0(double d),
  45.   Ft_Y1(double d),
  46.   Ft_Asin(double x),
  47.   Ft_Acos(double x),
  48.   Ft_Acosh(double x),
  49.   Ft_Asinh(double x),
  50.   Ft_Atanh(double x),
  51.   Ft_Cbrt(double x),
  52.   Ft_Cosh(double x),
  53.   Ft_Sinh(double x),
  54.   Ft_Tanh(double x),
  55.   Ft_Tan(double x),
  56.   Ft_Lgamma(double x),
  57.   Ft_Hypot(double x, double y),
  58.   Ft_Atan2(double x, double y),
  59.   Ft_Atan(double x),
  60.   Ft_octal(double x),
  61.   trunc(double x),
  62. #ifndef __HAVE_68881__
  63.   rint(double x),
  64. #endif
  65.   Ft_dbscan(char *s1, char *s2),
  66.   Ft_interp(double x),
  67.   Ft_minimum(double x, double y),
  68.   Ft_maximum(double x, double y),
  69.   Ft_sum(double *vec);
  70.  
  71. extern char *Ft_Read(void),
  72.   *Ft_Scan(char *s1, char *s2),
  73.   *Ft_DirName(char *s),
  74.   *Ft_FileName(char *s);
  75.  
  76. static struct {   /* Can never be erased  */
  77.     char     *name;
  78.     int      kval;
  79. } keywords[] = {
  80.     {"while", WHILE},
  81.     {"return", RETURN},
  82.     {"proc", PROC},
  83.     {"print", PRINT},
  84.     {"if",    IF},
  85.     {"func", FUNC},
  86.     {"for", FOR},
  87.     {"else",  ELSE},
  88.     {"continue", CONTINUE},
  89.     {"break", BREAK},
  90.     {"auto", AUTO},
  91.     {0, 0}
  92. };
  93.  
  94. static struct { /* can never be erased */
  95.     char *name;
  96.     double val;
  97. } bltinvars[] = {
  98.     {"if_value",  0},
  99.     {0, 0}
  100. };
  101.  
  102. static struct { /* can never be erased */
  103.     char *name;
  104.     double val;
  105. } bltinconsts[] = {
  106.     {"pi", M_PI},
  107.     {"param", 0},
  108.     {"e",  M_E},
  109.     {"data",  0},
  110.     {"chi2",  0},
  111.     {0, 0}
  112. };
  113.  
  114. static struct {  /* can never be erased */
  115.     char *name;
  116.     char *string;
  117. } bltinstrconsts[] = {
  118.     {"Tmp",  ""},
  119.     {"ReadFile", ""},
  120.     {"Cwd", ""},
  121.     {0, 0}
  122. };
  123.  
  124. static struct {  /* can never be erased */
  125.     char *name;
  126.     double (*func)();
  127. } builtins0[] = {
  128.     {"vread", Ft_vread},
  129.     {"rand", Ft_Rand},
  130.     {0, 0}
  131. };
  132.  
  133. static struct {  /* can never be erased */
  134.     char *name;
  135.     double (*func)();
  136. } builtins1vec[] = {
  137.     {"sum", Ft_sum},
  138.     {0, 0}
  139. };
  140.  
  141. static struct {  /* can never be erased */
  142.     char *name;
  143.     double (*func)();
  144. } builtins1[] = {
  145.     {"trunc", trunc},
  146.     {"tanh", Ft_Tanh},
  147.     {"tan", Ft_Tan},
  148.     {"srand", Ft_Srand},
  149.     {"sqrt", Ft_Sqrt},
  150.     {"sinh", Ft_Sinh},
  151.     {"sin", sin},
  152.     {"sech", Ft_Sech},
  153.     {"sec", Ft_Sec},
  154.     {"rint", rint},
  155.     {"octal", Ft_octal},
  156.     {"log", Ft_Log10},
  157.     {"ln", Ft_Log},
  158.     {"lgamma", Ft_Lgamma},
  159.     {"interp", Ft_interp},
  160.     {"int", Ft_integer},
  161.     {"floor", floor},
  162.     {"exp", Ft_Exp},
  163. #if !defined(HPUX) && !defined(AMIGA) 
  164.     {"erfc", erfc},
  165.     {"erf", erf},
  166. #endif
  167.     {"csch", Ft_Csch},
  168.     {"csc", Ft_Csc},
  169.     {"coth", Ft_Coth},
  170.     {"cot", Ft_Cot},
  171.     {"cosh", Ft_Cosh},
  172.     {"cos", cos},
  173.     {"ceil", ceil},
  174.     {"cbrt", Ft_Cbrt},
  175.     {"besy1", Ft_Y1},
  176.     {"besy0", Ft_Y0},
  177. #if !defined(HPUX) && !defined(AMIGA)
  178.     {"besj1", j1},
  179.     {"besj0", j0},
  180. #endif
  181.     {"atanh", Ft_Atanh},
  182.     {"atan", Ft_Atan},
  183.     {"asinh", Ft_Asinh},
  184.     {"asin", Ft_Asin},
  185.     {"acosh", Ft_Acosh},
  186.     {"acos", Ft_Acos},
  187.     {"abs", fabs},
  188.     {0, 0}
  189. };
  190.  
  191. static struct {  /* can never be erased */
  192.     char *name;
  193.     double (*func)();
  194. } builtins2[] = {
  195.     {"min", Ft_minimum},
  196.     {"max", Ft_maximum},
  197.     {"hypot", Ft_Hypot},
  198.     {"besyn", Ft_Yn},
  199.     {"besjn", Ft_Jn},
  200.     {"atan2", Ft_Atan2},
  201.     {0, 0}
  202. };
  203.  
  204. static struct {  /* can never be erased */
  205.     char *name;
  206.     double (*func)();
  207. } strbuiltins2[] = {
  208.     {"scan", Ft_dbscan},
  209.     {0, 0}
  210. };
  211.  
  212. static struct {  /* can never be erased */
  213.     char *name;
  214.     char *(*func)();
  215. } builtins0str[] = {
  216.     {"Read", Ft_Read},
  217.     {0, 0}
  218. };
  219.  
  220. static struct {  /* can never be erased */
  221.     char *name;
  222.     char *(*func)();
  223. } builtins1str[] = {
  224.     {"DirName", Ft_DirName},
  225.     {"FileName", Ft_FileName},
  226.     {0, 0}
  227. };
  228.  
  229. static struct {  /* can never be erased */
  230.     char *name;
  231.     char *(*func)();
  232. } builtins2str[] = {
  233.     {"Scan", Ft_Scan},
  234.     {0, 0}
  235. };
  236.  
  237. static int Argno = 0;
  238.  
  239.  
  240. extern void Ft_matherror (char *s1, char *s2, int lino);
  241.  
  242. void Ft_initparser(void)
  243. {
  244.     int i;
  245.     Symbol *s;
  246.  
  247.     for (i = 0;keywords[i].name; i++) {
  248.         s = Ft_install(keywords[i].name, keywords[i].kval, 1);
  249.     }
  250.     for (i = 0;bltinstrconsts[i].name; i++) {
  251.         s = Ft_install(bltinstrconsts[i].name, BLTINSTRCONST, 1);
  252.         s->u.str = "undefined";
  253.     }
  254.     for (i = 0;bltinvars[i].name; i++) {
  255.         s = Ft_install(bltinvars[i].name, BLTINVAR, 1);
  256.         s->u.val = bltinvars[i].val;
  257.     }
  258.     for (i = 0;bltinconsts[i].name; i++) {
  259.         s = Ft_install(bltinconsts[i].name, BLTINCONST, 1);
  260.         s->u.val = bltinconsts[i].val;
  261.     }
  262.     for (i = 0;builtins0[i].name; i++) {
  263.         s = Ft_install(builtins0[i].name, BLTIN0, 1);
  264.         s->u.ptr = builtins0[i].func;
  265.     }
  266.     for (i = 0;builtins1[i].name; i++) {
  267.         s = Ft_install(builtins1[i].name, BLTIN1, 1);
  268.         s->u.ptr = builtins1[i].func;
  269.     }
  270.     for (i = 0;builtins2[i].name; i++) {
  271.         s = Ft_install(builtins2[i].name, BLTIN2, 1);
  272.         s->u.ptr = builtins2[i].func;
  273.     }
  274.     for (i = 0;builtins0str[i].name; i++) {
  275.         s = Ft_install(builtins0str[i].name, BLTIN0STR, 1);
  276.         s->u.ptr = (double (*)()) (builtins0str[i].func);
  277.     }
  278.     for (i = 0;builtins1str[i].name; i++) {
  279.         s = Ft_install(builtins1str[i].name, BLTIN1STR, 1);
  280.         s->u.ptr = (double (*)()) (builtins1str[i].func);
  281.     }
  282.     for (i = 0;builtins2str[i].name; i++) {
  283.         s = Ft_install(builtins2str[i].name, BLTIN2STR, 1);
  284.         s->u.ptr = (double (*)()) (builtins2str[i].func);
  285.     }
  286.     for (i = 0;strbuiltins2[i].name; i++) {
  287.         s = Ft_install(strbuiltins2[i].name, STRBLTIN2, 1);
  288.         s->u.ptr = strbuiltins2[i].func;
  289.     }
  290.     for (i = 0;builtins1vec[i].name; i++) {
  291.         s = Ft_install(builtins1vec[i].name, BLTIN1VEC, 1);
  292.         s->u.ptr = builtins1vec[i].func;
  293.     }
  294. }
  295.  
  296. static Symbol *symlist = 0;
  297. static AutoSymbol *autosymlist = 0;
  298.  
  299. #include <stdio.h>
  300. #include <string.h>
  301.  
  302. Symbol *Ft_Symlist(void)
  303. {
  304.     return(symlist);
  305. }
  306.  
  307. Symbol *Ft_lookup(char *s)
  308. {
  309.     Symbol *sp;
  310.  
  311.     if (!s)
  312.         return(NULL);
  313.     for (sp = symlist; sp != (Symbol *)0; sp = sp->next) {
  314.         if (strcmp(sp->name, s) == 0) {
  315.             return(sp);
  316.         }
  317.     }
  318.     return(NULL);
  319. }
  320.  
  321. int Ft_autolookup(char *s, int level)
  322. {
  323.     AutoSymbol *sp;
  324.  
  325.     if (!s)
  326.         return(0);
  327.     for (sp = autosymlist; sp != (AutoSymbol *)0; sp = sp->next) {
  328.         if (strcmp(sp->name, s) == 0) {
  329.             if (level) {
  330.                 if (sp->level >= level) {
  331.                     return(sp->argno);
  332.                 }
  333.                 else {  /* larger level is at the beginning */
  334.                     return(0);
  335.                 }
  336.             }
  337.             else if (sp->level == 0) {
  338.                 return(sp->argno);
  339.             }
  340.         }
  341.     }
  342.     return(0);
  343. }
  344.  
  345. int Ft_autoinstall(char *s, int type, int level)
  346. {
  347.     AutoSymbol *sp;
  348.     extern int Argno;
  349.  
  350.     if (strlen(s) > MAXVARNAME) {
  351.         Ft_matherror("autoinstall: %s: Name too long.", s, 0);
  352.     }
  353.     if ((sp = (AutoSymbol *)malloc(sizeof(AutoSymbol))) == (AutoSymbol *)0) {
  354.         Ft_matherror("autoinstall: Allocation error.", NULL, 0);
  355.     }
  356.     if ((sp->name = (char *)malloc(strlen(s)+1)) == (char *)0) {
  357.         Ft_matherror("autoinstall: Allocation error.", NULL, 0);
  358.     }
  359.     strcpy(sp->name, s);
  360.     sp->level = level;
  361.     sp->type = type;
  362.     sp->argno = ++Argno;
  363.     sp->next = autosymlist;
  364.     autosymlist = sp;
  365.     return(Argno);
  366. }
  367.  
  368. Symbol *Ft_install(char *s, int t, int size)
  369. {
  370.     Symbol *sp;
  371.     
  372.     sp = Ft_geninstall(s, t, size);
  373.     sp->next = symlist;
  374.     symlist = sp;
  375.     return(sp);
  376. }
  377.  
  378. Symbol *Ft_geninstall(char *s, int t, int size)
  379. {
  380.     Symbol *sp;
  381.     extern double *Ft_dvector(int nl, int nh);
  382.  
  383.     if (strlen(s) > MAXVARNAME) {
  384.         Ft_matherror("install: %s: Name too long.", s, 0);
  385.     }
  386.     if ((sp = (Symbol *)malloc(sizeof(Symbol))) == (Symbol *)0) {
  387.         Ft_matherror("install: Allocation error.", NULL, 0);
  388.     }
  389.     if ((sp->name = (char *)malloc(strlen(s)+1)) == (char *)0) {
  390.         Ft_matherror("install: Allocation error.", NULL, 0);
  391.     }
  392.     if (t == VEC || t == UNDEFVEC || t == PARAM) {
  393.         if ((sp->u.vec = Ft_dvector(1, size)) == (double *)0) {
  394.             Ft_matherror("install: Allocation error.", NULL, 0);
  395.         }
  396.     }
  397.     else if (t == STRING || t == UNDEFSTRVAR ||
  398.              t == STRVAR || t == BLTINCONST) {
  399.         if (t != UNDEFSTRVAR) {
  400.             if ((sp->u.str = (char *)malloc(size+1)) == NULL) {
  401.                 Ft_matherror("install: Allocation error.", NULL, 0);
  402.             }
  403.         }
  404.         else {
  405.             sp->u.str = (char *)NULL;
  406.         }
  407.     }
  408.     sp->size.val = size;
  409.     strcpy(sp->name, s);
  410.     sp->type = t;
  411.     return(sp);
  412. }
  413.  
  414. int Ft_autosymremove(int level)
  415. {
  416.     AutoSymbol *sp, *sprevious;
  417.     AutoSymbol *spresent;
  418.     extern int Argno;
  419.     int removed = 0;
  420.  
  421.     sprevious = sp = autosymlist;
  422.     while (sp != (AutoSymbol *)0) {
  423.         if (sp->level >= level) {
  424.             if (sp->type == AUTO)
  425.                 removed++;
  426.             spresent = sp;
  427.             if (spresent == autosymlist) {  /* first one ? */
  428.                 autosymlist = sp->next;
  429.                 sp = sp->next;
  430.             }
  431.             else {
  432.                 sprevious->next = sp->next;
  433.                 sp = sp->next;
  434.             }
  435.             free(spresent->name);
  436.             free((char *)spresent);
  437.             Argno--;
  438.         }
  439.         else {
  440.             sprevious = sp;
  441.             sp = sp->next;
  442.         }
  443.     }
  444.     return(removed);
  445. }
  446.  
  447.     /* remove vectors or variables on request */
  448. int Ft_symremove(char *name, int verb)
  449. {
  450.     Symbol *sp, *sprevious;
  451.     Symbol *spresent;
  452.     int found;
  453.     int all;
  454.     extern void Ft_free_dvector(double *v, int nl, int nh);
  455.     extern void Ft_resetprog(void);
  456.  
  457.     found = all = (strcmp(name, "@all") == 0);
  458.     if (all) {  /* reset machine vector */
  459.         Ft_resetprog();
  460.     }
  461.     sprevious = sp = symlist;
  462.     while (sp != (Symbol *)0) {
  463.         switch(sp->type) {
  464.             case BLTINVAR:
  465.             case BLTINSTRVAR:
  466.             case BLTINCONST:
  467.             case BLTINSTRCONST:
  468.                 if (strcmp(sp->name, name) == 0 && !all) {
  469.                     fprintf(stderr, "free: %s: Cannot be removed.\n", name);
  470.                     return(ERRR);
  471.                 }
  472.                 break;
  473.             case STRCONST:
  474.             case CONST:
  475.                 if (strcmp(sp->name, name) == 0 && !all) {
  476.                     fprintf(stderr,
  477.                     "free: %s now a constant. Unlock first.\n", name);
  478.                     return(ERRR);
  479.                 }
  480.                 break;
  481.             case STRING:
  482.                 if (!all) {
  483.                     break;
  484.                 }
  485.             case VEC:
  486.             case UNDEFVEC:
  487.             case STRVAR:
  488.             case UNDEFSTRVAR:
  489.             case VAR:
  490.             case UNDEFVAR:
  491.             case PARAM:
  492.             case FUNCSYM:
  493.             case PROCSYM:
  494.                 if (strcmp(sp->name, name) != 0 && !all) {
  495.                     break;
  496.                 }
  497.                 found = 1;
  498.                 spresent = sp;
  499.                 if (spresent == symlist) {  /* first one ? */
  500.                     symlist = sp->next;
  501.                     sp = sp->next;
  502.                 }
  503.                 else {
  504.                     sprevious->next = sp->next;
  505.                     sp = sp->next;
  506.                 }
  507.                 free(spresent->name);
  508.                 if (spresent->type == VEC || spresent->type == UNDEFVEC
  509.                 || spresent->type == PARAM) {
  510.                     Ft_free_dvector(spresent->u.vec, 1, spresent->size.val);
  511.                 }
  512.                 if (spresent->type == STRVAR || spresent->type == STRCONST ||
  513.                 spresent->type == UNDEFSTRVAR) {
  514.                     if (spresent->u.str)
  515.                         free(spresent->u.str);
  516.                 }
  517.                 free((char *)spresent);
  518.                 continue;
  519.         default:
  520.             if (strcmp(sp->name, name) == 0) {
  521.                 fprintf(stderr,
  522.                 "%s: Not allowed to remove built-in definitions.\n", name);
  523.                 return(ERRR);
  524.             }
  525.             break;
  526.         }
  527.         sprevious = sp;
  528.         sp = sp->next;
  529.     }
  530.  
  531.     if (!found && verb) {
  532.         fprintf(stderr, "%s: No such variable.\n", name);
  533.         return(ERRR);
  534.     }
  535.     return(0);
  536. }
  537.  
  538. #ifndef NOMALLINFO
  539. int Ft_showmem(void)
  540. {
  541.     struct mallinfo mal;
  542.  
  543.     mal = mallinfo();
  544.     fprintf(stderr, "%28s: %d\n", "Arena", mal.arena);
  545.     fprintf(stderr, "%28s: %d\n", "Number of ordinary blocks", mal.ordblks);
  546.     fprintf(stderr, "%28s: %d\n", "Ordinary block space in use", mal.uordblks);
  547.     fprintf(stderr, "%28s: %d\n", "Ordinary block space free", mal.fordblks);
  548.     fprintf(stderr, "%28s: %d\n", "Number of small blocks", mal.smblks);
  549.     fprintf(stderr, "%28s: %d\n", "Small block space in use", mal.usmblks);
  550.     fprintf(stderr, "%28s: %d\n", "Small block space free", mal.fsmblks);
  551.     fprintf(stderr, "%28s: %d\n", "Number of holding blocks", mal.hblks);
  552.     fprintf(stderr, "%28s: %d\n", "Block header space", mal.hblkhd);
  553.     fprintf(stderr, "%28s: %d\n", "Keepcost space", mal.keepcost);
  554.     return(0);
  555. }
  556. #endif
  557.  
  558. Symbol *Ft_symlist(void)
  559. {
  560.     return(symlist);
  561. }
  562.  
  563. int Ft_lock(int i, char *name, char *fname)  /* lock on 1, unlock on 0  */
  564. {
  565.     static char *vnam[] = {"constant", "variable", 0};
  566.     static int type[] = {CONST, VAR, 0};
  567.     static int bltintype[] = {BLTINCONST, BLTINVAR, 0};
  568.     static int strtype[] = {STRCONST, STRVAR, 0};
  569.     static int bltinstrtype[] = {BLTINSTRCONST, BLTINSTRVAR, 0};
  570.     Symbol *sp;
  571.  
  572.     if ((sp = Ft_lookup(name)) == 0) {
  573.         if (i) {
  574.             fprintf(stderr, "%s: %s: No such variable or constant.\n",
  575.             fname, name);
  576.             return(ERRR);
  577.         }
  578.         fprintf(stderr, "Warning: %s: %s: No such variable or constant.\n",
  579.         fname, name);
  580.         return(0);
  581.     }
  582.     if (sp->type == type[i]) {
  583.         sp->type = type[!i];
  584.     }
  585.     else if (sp->type == bltintype[i]) {
  586.         sp->type = bltintype[!i];
  587.     }
  588.     else if (sp->type == strtype[i]) {
  589.         sp->type = strtype[!i];
  590.     }
  591.     else if (sp->type == bltinstrtype[i]) {
  592.         sp->type = bltinstrtype[!i];
  593.     }
  594.     else if (sp->type == type[!i] || sp->type == strtype[!i] ||
  595.     sp->type == bltintype[!i] || sp->type == bltinstrtype[!i]) {
  596.         fprintf(stderr, "Warning: %s: %s: Already a %s.\n",
  597.         fname, name, vnam[!i]);
  598.     }
  599.     else {
  600.         fprintf(stderr, "%s: %s: Not a regular variable.\n", fname, name);
  601.     }
  602.     return(0);
  603. }
  604.  
  605. char *Ft_var_generator(char *text, int state)
  606. {
  607.     static int len;
  608.     static Symbol *smp;
  609.     register Symbol *sp;
  610.     register int tp;
  611.     char *fname;
  612.     extern int Ft_Mode;
  613.  
  614.     if (state == 0) {
  615.         smp = symlist;
  616.         len = strlen(text);
  617.     }
  618.     while (smp != (Symbol *)0) {
  619.         sp = smp;
  620.         smp = smp->next;
  621.         tp = sp->type;
  622.         if (tp == STRING)
  623.             continue;
  624.         /* the following line depends on the order in parse.y */
  625.         if (Ft_Mode == FMODE && (tp < VAR || tp > BLTINSTRCONST))
  626.             continue;
  627.         if (strncmp(sp->name, text, len) == 0) {
  628.             if ((fname = (char *) malloc(strlen(sp->name)+1)) == NULL) {
  629.                 fputs("Allocation error in var_gen.\n", stderr);
  630.                 Ft_catcher(ERRR);
  631.             }
  632.             strcpy(fname, sp->name);
  633.             return(fname);
  634.         }
  635.     }
  636.     return(NULL);
  637. }
  638.  
  639. int Ft_cleansym(void)
  640. {
  641.     Symbol *sp, *sprevious;
  642.     Symbol *spresent;
  643.     extern void Ft_free_dvector(double *v, int nl, int nh);
  644.  
  645.     sprevious = sp = symlist;
  646.     while (sp != (Symbol *)0) {
  647.         if (sp->type == UNDEFVEC || sp->type == UNDEFVAR ||
  648.             sp->type == UNDEFSTRVAR) {
  649.             spresent = sp;
  650.             if (spresent == symlist) {  /* first one ? */
  651.                 symlist = sp->next;
  652.                 sp = sp->next;
  653.             }
  654.             else {
  655.                 sprevious->next = sp->next;
  656.                 sp = sp->next;
  657.             }
  658.             free(spresent->name);
  659.             if (spresent->type == UNDEFVEC) {
  660.                 Ft_free_dvector(spresent->u.vec, 1, spresent->size.val);
  661.             }
  662.             if (spresent->type == UNDEFSTRVAR) {
  663.                 if (spresent->u.str)
  664.                     free(spresent->u.str);
  665.             }
  666.             free((char *)spresent);
  667.             continue;
  668.         }
  669.         sprevious = sp;
  670.         sp = sp->next;
  671.     }
  672.     return(0);
  673. }
  674.  
  675.